﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml.Serialization;
using System.Collections;
using Org.Eurekaa.DNJ.Collections;
using System.Reflection;

namespace Org.Eurekaa.DNJ.Config
{

    [Serializable()]
    public class DNJResource : IComparable
    {
        [XmlAttribute("id")]
        public String ID { get; set; }

        [XmlAttribute("assembly")]
        public String Assembly { get; set; }

        [XmlIgnore]
        public int Order { get; set; }

        [XmlIgnore]
        public bool LoadMe { get; set; }

        [XmlIgnore]
        public String InnerScript { get; set; }

        public List<DNJResource> Resources = new List<DNJResource>();
        public DNJResource()
        {
            Order = 0;
        }

        public DNJResource(string id, string asm)
        {
            this.ID = id;
            this.Assembly = asm;
        }

        public override string ToString()
        {
            return Assembly;
        }
        #region IComparable Members

        public int CompareTo(object obj)
        {
            return this.Order.CompareTo((obj as DNJResource).Order);
        }

        #endregion
    }

   
    [Serializable()]
    public static class ResourcesConfig
    {
        //private static List<DNJResource> _resources = new List<DNJResource>();
        private static Hashtable resources = new Hashtable();
        private static Hashtable LoadedResources = new Hashtable();
        private static bool loaded = false;

        public static Hashtable Resources
        {
            get
            {
                return resources;
            }
        }
        private static int GetMaxResOrder()
        {
            int max = 0;

            foreach (DNJResource r in resources.Values)
            {
                if (r.Order > max) max = r.Order;
            }
            
            return max;
        }        
        public static void AddResourcesList(List<DNJResource> source)
        {
            foreach (DNJResource r in source)
                AddResource(r, Resources.Count);
        }


        private static void AddResource(DNJResource r, int order)
        {            
                string resKey = r.ID;
                if (String.IsNullOrEmpty(r.Assembly) && r.Resources != null && r.Resources.Count > 0) //this is likely a namespace
                {                    
                    foreach (DNJResource subR in r.Resources)
                    {
                        resKey = r.ID + "." + subR.ID;
                        subR.Order = order;
                        subR.ID = resKey;
                        resources[resKey] = subR;
                    }

                }
                else
                {
                    r.Order = order;
                    r.ID = resKey;
                    resources[resKey] = r;
                }
            
        }

        public static void AddResource(string id, string assembly)
        {
            AddResource(new DNJResource(id, assembly), Resources.Count+1000);
        }

        public static void AddResourceInnerScript(string id, String script)
        {
            if (resources[id] != null)
                (resources[id] as DNJResource).InnerScript = script;
        }

        public static string GetResourceString()
        {
            string result = "";
            ArrayList res = new ArrayList(resources.Values);

            int order = Resources.Count;            

            res.Sort();
            Hashtable namespaces = new Hashtable();
            foreach (DNJResource r in res)
            {
                string[] tokens = r.ID.Split('.');
                if (tokens.Length == 2) //namespace
                {
                    string ns = tokens[0];
                    if (string.IsNullOrEmpty(namespaces[ns] as string))
                        namespaces[ns] = tokens[1];
                    else
                        namespaces[ns] += "," + tokens[1];

                    ns += "[]";
                    if (result.IndexOf(ns) < 0)
                        result += ns + ",";
                }
                else
                    result += r.ID + ",";
            }

            foreach (string key in namespaces.Keys)
            {
                result = result.Replace(key + "[]", key + "[" + (namespaces[key] as string).TrimEnd(new char[] { ',' }) + "]");
            }
            return result;
        }
        public static void LoadConfig(String AssemblyName, String XmlResourceName)
        {
            XmlResourceName = AssemblyName + "." + XmlResourceName;
            if (LoadedResources.ContainsKey(XmlResourceName)) return;

            XmlSerializer deserializer = new XmlSerializer(typeof(List<DNJResource>));


            //XmlSerializer s = new XmlSerializer(typeof(DNJGenericCollection<DNJResource>));
            //TextWriter w = new StreamWriter(@"C:\ser.xml");
            //s.Serialize(w, _resources);
            //w.Close();
            Assembly assembly = null;
            try
            {
                assembly = Assembly.Load(AssemblyName);
            }
            catch {
                return;
            }



            Stream stream = assembly.GetManifestResourceStream(XmlResourceName);

            if (stream == null) return;
            List<DNJResource> res;
            res = (List<DNJResource>)deserializer.Deserialize(stream);
            stream.Close();


            AddResourcesList(res);

            LoadedResources[XmlResourceName] = true;
           
            //return res;
        }

    }
}
